﻿#pragma once

#include "tgafilebuffer.h"
#include <cstdint>
#include <vector>
#include <string>
#include <memory>

/// TGA format specification
/// brief:
/// http://www.paulbourke.net/dataformats/tga/
/// full:
/// https://www.ludorg.net/amnesia/TGA_File_Format_Spec.html
/// https://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf


typedef enum TgaImageType_t : int {
	ImageType_0 = 0,   // no image data
	ImageType_1,       // uncompressed, color-mapped image 
	ImageType_2,       // uncompressed, true-color image
	ImageType_3,       // uncompressed, black-and-white image
	ImageType_9 = 9,   // run-length encoded, color-mapped image
	ImageType_10 = 10, // run-length encoded, true-color image
	ImageType_11 = 11, // true-color image, black-and-white image
} TgaImageType;


struct TGAColor
{
	uint8_t rgba[4] = { 0, 0, 0, 0 };
	uint8_t spp = 4;
	uint8_t& operator[](const int i) { return rgba[i]; }
};

class TGAImage
{ // 2D image
public:
	enum Format { GRASCALE = 1, RGB = 3, RGBA = 4 };

	TGAImage() = default;
	TGAImage(int w, int h, int bpp);
	TGAImage(int w, int h, int bpp, bool intelbyteordering);

	bool is_new_tga(const std::string& filepath); // detect signature
	bool read_from_tga_file(const std::string& filepath);
	bool write_to_tga_file(const std::string& filepath, bool vflip = true, bool rle = true) const;
	void flip_horizontally();
	void flip_vertically();

	void set_intel_byte_ordering(bool val) { intelbyteordering = val; }
	bool is_intel_byte_ordering() const { return intelbyteordering; }

	void set_image_id(const std::vector<uint8_t>& imageid);
	const std::vector<uint8_t>& image_id() const;

	int width() const { return w; }
	int height() const { return h; }

private:
	bool load_header(std::ifstream& in);
	bool load_image_id(std::ifstream& in);
	bool load_rle_data(std::ifstream& in);
	bool load_footer(std::ifstream& in);
	bool unload_header(std::ofstream& out, bool vflip, bool rle) const;
	bool unload_image_id(std::ofstream& out) const;
	bool unload_rle_data(std::ofstream& out) const;
	bool unload_develop_area(std::ofstream& out) const;
	bool unload_extension_area(std::ofstream& out) const;
	bool unload_footer(std::ofstream& out) const;
	void ensure_filebuffer_not_null();

	std::unique_ptr<TGAFileBuffer> filebuffer;

	int w = 0;
	int h = 0;
	uint8_t bpp = 0; // bytes per pixel
	std::vector<uint8_t> data{0};
	bool intelbyteordering = true;
};
